//
//  StatusListViewModel.swift
//  XS微博
//
//  Created by 王小帅 on 2016/11/16.
//  Copyright © 2016年 王小帅. All rights reserved.
//

import Foundation
import YYModel
import SDWebImage

// 因为测试app 微博服务器有请求限制，如果过于频繁请求回被拉黑所以要做限制
fileprivate var maxPullNmuber = 3

/// 微博列表模型
/// mvvm 开发模式的mv
/// 因为不需要用 kvc 只是单纯的函数封装 所以可以不继承任何父类
class StatusListViewModel {
    
    // 懒加载微博数组
    lazy var statusList = [StatusViewModel]()
    // 记录坏请求次数,如果达到了最大的请求计数 则不再访问服务器
    var badPullNumber = 0
    
    
    // 获取微博数组的方法
    func loadStatusList(pullUp:Bool ,completed: @escaping (_ isSuccess: Bool, _ shouldReloadData: Bool)->()) {
        
        // 判断是否达到了坏请求限制，这里指判断上拉久够了
        if pullUp && badPullNumber > maxPullNmuber {
        
            // 回调并返回 这里娶不到isSuccess 不知道为啥？！
            completed(true, false)
            return
        }
        
        // 判断是否上拉刷新
        let sinceID = pullUp ? 0 : (statusList.first?.status.id ?? 0)
        // 这里注意：如果maxid 有值 返回ID小于或等于max_id的微博
        // 所以会产生一条重复的数据 所以maxid要-1
        let maxID = !pullUp ? 0 : (statusList.last?.status.id ?? 0)
        
        // 在建立的单条微博视图模型后，这个方法要修改！以前是返回微博模型数组，现在要转换为微博视图模型数组
        XSNetworkTools.shared.statusListRequest(since_id: sinceID, max_id: maxID) {
            (list, isSuccess) in
            //如果请求失败直接返回
            if !isSuccess {
            
                completed(false, false)
                return
            }
            
            // 存储微博视图模型的数组
            // 这里请求到的list 是包含狠多信息的json 我只要status
            let statusJson = list?["statuses"] as! [[String: AnyObject]]
            
            // 装有单个微博视图模型的数组
            var array = [StatusViewModel]()
            // 遍历数组实现转换
            for dict in statusJson {
            
                let model = XSStatusModel.yy_model(with: dict)
                let statusVM = StatusViewModel(model: model!)
                
                array.append(statusVM)
            }
            
            // 将结果字典 用yymodel 转化为模型（定义了单条微博视图模型后没有集成NSObject 不能使用yy转换）
//            let array = NSArray.yy_modelArray(with: XSStatusModel.self, json: statusJson) as! [XSStatusModel]
            
            // 上拉: 数据添加到最后,下拉: 数据添加到最前面
            if pullUp {
                self.statusList += array
            }else {
                self.statusList = array + self.statusList
            }
            
            print("获取了  \(array.count)  条数据 \(array)")
            
            // 判断坏访问
            if pullUp && array.count == 0 {
                
                self.badPullNumber += 1
                // 回调
                completed(isSuccess, false)
                
            }else {
                
                // 缓存单张图片
                self.cacheSingalPic(array: array, finished: completed)
                // 回调 被移动到了 缓存完成所有单张图片后在调用
//                completed(isSuccess, true)
            }
        }
    }
    
    
    
    /// 缓冲单张视图 用gcd多线程方式实现，只有等所有单张图片缓存完成采取回调刷新列表
    ///
    /// - Parameter array: 视图模型数组
    fileprivate func cacheSingalPic(array: [StatusViewModel], finished: @escaping (_ isSuccess: Bool, _ shouldReloadData: Bool)->()){
        
        // 定义组
        let group = DispatchGroup()
        
        // 获取要被缓存等单图url
        for vm in array {
            
            // 只有一张图的时候才缓存
            if vm.picUrls?.count != 1 {
                continue
            }

                // 守护下 如果没有图片地址就继续下一个循环
                guard let picurl = vm.picUrls?[0].thumbnail_pic,
                    let url = URL(string: picurl) else {
                        continue
                }
                
                // 入组了
                group.enter()
                // 下面使用 SDWebImage 的核心方法来下载图片，这个方法下载的图片会自动缓存到沙河，路径是MD5
                // 如果已经存在就不再去请求网络来
                SDWebImageManager.shared().downloadImage(with: url, options: [], progress: nil, completed: { (image, _, _, _, _) in
                    
                    // 到这里图片缓存完成 可以输出看下图片等大小
                    if let image = image,
                       let data = UIImagePNGRepresentation(image) {
                        
                        print("缓存图片完成 \(data.count / 1024)  K  image.size = \(image.size)")
                        
                        var vm1 = vm
                        // 调用更新单张照片到配图视图尺寸
                        vm1.updateSignalPicViewSize(image: image)
                    }
                    
                    
                    // 出组 一定记得在闭包等最后调用 否则任务执行不会被监听
                    group.leave()
                })
        }
        
        // 监听闭包执行完成
        group.notify(queue: DispatchQueue.main, execute: {
            // 这里用主线程去调用闭包回调 刷新界面
            finished(true, true)
        })
        
    }
}
